/*
 * SPI_M.c
 *
 * Created: 20.02.2013 17:06:58
 *  Author: saenko
 */ 

#include <avr/io.h>

#include "hardware.h"


#define cbi(reg,bit)	reg &= ~(_BV(bit))
#define sbi(reg,bit)	reg |= (_BV(bit))

#define SPI_OUT PB3
#define SPI_IN PB4
#define SPI_SS PB2
#define SPI_CLK PB5

#define SPI_OUT_1 sbi(PORTB,SPI_OUT)
#define SPI_OUT_0 cbi(PORTB,SPI_OUT)

#define SPI_SS_1 sbi(PORTB,SPI_SS)
#define SPI_SS_0 cbi(PORTB,SPI_SS)

#define SPI_CLK_1 sbi(PORTB,SPI_CLK)
#define SPI_CLK_0 cbi(PORTB,SPI_CLK)

void delay_spi(void)
{
	for(unsigned char i = 0; i<16; i++)
	{
		asm("nop");
	}
}


void spi_init(void)
{
	sbi(DDRB,SPI_OUT);	
	sbi(DDRB,SPI_SS);
	sbi(DDRB,SPI_CLK);
	cbi(DDRB,SPI_IN);
	
	SPI_SS_1;
	SPI_CLK_0;
	SPI_OUT_1;
}

void spi_write(unsigned char data)
{
	SPI_SS_0;
	delay_spi();
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(PORTB,SPI_IN)) SPI_OUT_1;
		else SPI_OUT_0;	
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
	delay_spi();
	SPI_SS_1;
}

unsigned char spi_read_reg(unsigned char data)
{
	unsigned char data_in;
	
	SPI_SS_0;
	delay_spi();
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;	
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
	delay_spi();

	for(unsigned char i = 0; i <8; i++)
	{
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;		
		data_in = data_in<<1;
		if(bit_is_set(PINB,SPI_IN)) data_in++;
		//else data_in<<0;	
		delay_spi();
		

	}	
	
	SPI_SS_1;	
	
	return data_in;
}

unsigned char spi_read_IRQ_status(void)
{
		unsigned char data = 0x6C;
		unsigned char data_in;
		
		SPI_SS_0;
		delay_spi();
		
		for(unsigned char i = 0; i <8; i++)
		{
			if(bit_is_set(data,7-i)) SPI_OUT_1;
			else SPI_OUT_0;
			
			delay_spi();
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
		}
		
		delay_spi();

		for(unsigned char i = 0; i <8; i++)
		{
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
			data_in = data_in<<1;
			if(bit_is_set(PINB,SPI_IN)) data_in++;
			//else data_in<<0;
			delay_spi();
			

		}
		
		for(unsigned char i = 0; i <8; i++)
		{
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
			delay_spi();
					

		}
		SPI_SS_1;
		
		return data_in;
}


unsigned char spi_write_reg(unsigned char reg, unsigned char data)
{
	unsigned char data_in;
	
	SPI_SS_0;
	delay_spi();
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(reg,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
			
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
	SPI_SS_1;
	
	return data_in;
}

void spi_send_pack(void)
{
	unsigned char data;
	
//start condition
	SPI_SS_0;
	delay_spi();

//send reset	
	data = 0x8F;
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
//send tr wth crc
	data = 0x91;
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}

//send cont wr reg
	data = 0x3D;
	
	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	

//data for 0x1D

	data = 0x00;

	for(unsigned char i = 0; i <8; i++)
	{
		if(bit_is_set(data,7-i)) SPI_OUT_1;
		else SPI_OUT_0;
		
		delay_spi();
		SPI_CLK_1;
		delay_spi();
		SPI_CLK_0;
	}
	
//data for 0x1E

data = 0x20;

for(unsigned char i = 0; i <8; i++)
{
	if(bit_is_set(data,7-i)) SPI_OUT_1;
	else SPI_OUT_0;
	
	delay_spi();
	SPI_CLK_1;
	delay_spi();
	SPI_CLK_0;
}

//data for FIFO
for(unsigned char j = 0; j<4; j++)
	{
		
		unsigned char data[] = {0x18,0x00,0x20,0x00};

		for(unsigned char i = 0; i <8; i++)
		{
			if(bit_is_set(data[j],7-i)) SPI_OUT_1;
			else SPI_OUT_0;
			
			delay_spi();
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
		}



	}
	
	SPI_SS_1;

}

unsigned char WriteSingle (unsigned char *pbuf, unsigned char lenght)
{
	
	unsigned char	i,j;
	
	//start condition
	SPI_SS_0;
	delay_spi();
	
	while(lenght > 0)
	{
		*pbuf = (0x1f &*pbuf);	/* register address */

		for(unsigned char i = 0; i <8; i++)
		{
			if(bit_is_set(*pbuf,7-i)) SPI_OUT_1;
			else SPI_OUT_0;
					
			delay_spi();
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
		}
		lenght--;
		
		*pbuf++;
		
		for(unsigned char i = 0; i <8; i++)
		{
			if(bit_is_set(*pbuf,7-i)) SPI_OUT_1;
			else SPI_OUT_0;
			
			delay_spi();
			SPI_CLK_1;
			delay_spi();
			SPI_CLK_0;
		}
		
		lenght--;
		
		
	}	

	SPI_SS_1;

}

void InitialSettings(void)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~*/
	unsigned char	command[2];
	/*~~~~~~~~~~~~~~~~~~~~~~~*/

	command[0] = ModulatorControl;
	command[1] = 0x21;   //6.78 MHz
	//       command[1] = 0x31;  //13.56 MHz

	WriteSingle(command, 2);
}